package com.xique.door.project.sfm.biz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xique.common.core.utils.OrikaUtil;
import com.xique.common.core.utils.StringUtils;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.door.project.sfm.api.ISfmApi;
import com.xique.door.project.sfm.bean.domain.JrwhUser;
import com.xique.door.project.sfm.bean.dto.SfmInsertPeopleDTO;
import com.xique.door.project.sfm.bean.request.SfmInsertPeopleRequest;
import com.xique.door.project.sfm.bean.request.SfmOpenDoorRequest;
import com.xique.door.project.sfm.bean.request.SfmSelectHouseRequest;
import com.xique.door.project.sfm.bean.vo.*;
import com.xique.door.project.sfm.biz.service.ISfmHomeBizService;
import com.xique.door.project.sfm.service.IJrwhUserService;
import com.xique.door.project.sfm.utils.SfmMD5;
import com.xique.door.project.sfm.utils.SfmUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SfmHomeBizServiceImpl implements ISfmHomeBizService {

    @Autowired
    private ISfmApi sfmApi;

    @Value("${sfm.appid}")
    private String appid;

    @Value("${sfm.appsecret}")
    private String appsecret;

    public static final String CODE_TAG = "code";

    public static final String MSG_TAG = "msg";

    public static final String SUCCESS_TAG = "1";

    @Autowired
    private IJrwhUserService jrwhUserService;

    private String getTimestemp(){
        return new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
    }

    @Override
    public AjaxResult getProvince() {
        Map<String,String> params= new HashMap<>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);

        String result = sfmApi.getProvince(params);
        System.out.println(result);
        return AjaxResult.success(result);
    }

    @Override
    public AjaxResult getCityByProvinceNo(String provinceNo) {
        Map<String,String> params= new HashMap<>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        Map<String,String> data= new HashMap<>();
        data.put("province_no", provinceNo);
        params.put("data",JSONObject.toJSONString(data));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.getCity(params);
        return  AjaxResult.success(result);
    }

    @Override
    public AjaxResult getCommunityByCity(String provinceNo, String cityNo) {
        Map<String,String> params= new HashMap<>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        Map<String,String> data= new HashMap<>();
        data.put("community_provinceno",provinceNo);
        data.put("community_cityno",cityNo);
        params.put("data",JSONObject.toJSONString(data));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.getCommunityByCity(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return AjaxResult.error(jsonObject.get(MSG_TAG).toString());
        }
        Object dataObj = jsonObject.get("data");
        List<SfmCommunityVO> sfmCommunityVOS = JSONObject.parseArray(dataObj.toString(), SfmCommunityVO.class);
        List<SfmCommunityVO> returnVO = sfmCommunityVOS.stream().filter(e -> !"1635590032234426".equals(e.getCommunityNo())).collect(Collectors.toList());
        return  AjaxResult.success(returnVO);
    }

    @Override
    public AjaxResult getBuildingByCommunityNo(String communityNo) {
        Map<String,String> params= new HashMap<>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        params.put("communityno", communityNo);
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.getBuildingByCommunityNo(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return AjaxResult.error(jsonObject.get(MSG_TAG).toString());
        }
        Object dataObj = jsonObject.get("data");
        List<SfmBuildingVO> sfmBuildingVOS = JSONObject.parseArray(dataObj.toString(), SfmBuildingVO.class);
        return  AjaxResult.success(sfmBuildingVOS);
    }

    @Override
    public AjaxResult getHouseByBuildingNo(String buildingNo, String communityNo) {
        Map<String,String> params=new HashMap<String,String>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        params.put("communityno", communityNo);
        Map<String,String> data= new HashMap<>();
        data.put("building_no",buildingNo);
        params.put("data",JSONObject.toJSONString(data));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.getHouseByBuildingNo(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return AjaxResult.error(jsonObject.get(MSG_TAG).toString());
        }
        Object dataObj = jsonObject.get("data");
        List<SfmHouseVO> sfmHouseVOS = JSONObject.parseArray(dataObj.toString(), SfmHouseVO.class);
        return  AjaxResult.success(sfmHouseVOS);
    }

    @Override
    public AjaxResult getListByHouseNo(String houseNo, String communityNo, String pageindex, String pagesize) {
        Map<String,String> params=new HashMap<String,String>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        params.put("communityno", communityNo);
        Map<String,String> data=new HashMap<String,String>();
        data.put("house_no", houseNo);
        data.put("pageindex", pageindex);
        data.put("pagesize", pagesize);
        params.put("data",JSONObject.toJSONString(data));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.getListByHouseNo(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return AjaxResult.error(jsonObject.get(MSG_TAG).toString());
        }
        Object dataObj = jsonObject.getJSONObject("data").get("data");
        List<SfmUserVO> sfmUserVOS = JSONObject.parseArray(dataObj.toString(), SfmUserVO.class);
        return  AjaxResult.success(sfmUserVOS);
    }

    @Override
    public AjaxResult insertPeople(SfmInsertPeopleRequest request) {
        Map<String,String> params=new HashMap<String,String>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        params.put("communityno", request.getCommunityNo());
        SfmInsertPeopleDTO dto = new SfmInsertPeopleDTO();
        try {
            ObjectMapper mapper = new ObjectMapper();
            dto = OrikaUtil.convert(JSONObject.parseObject(mapper.writeValueAsString(request)), SfmInsertPeopleDTO.class);
        } catch (JsonProcessingException e) {
            return AjaxResult.error(e.toString());
        }
        params.put("data", JSONObject.toJSONString(dto));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.insertPeople(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return AjaxResult.error(jsonObject.get(MSG_TAG).toString());
        }
        String peopleNo = jsonObject.getJSONObject("data").getString("people_no");

        // TODO 绑定住户
        Map<String,String> map = new HashMap<String,String>();
        map.put("appid", appid);
        map.put("timestemp", getTimestemp());
        map.put("communityno", request.getCommunityNo());
        Map<String,String> data=new HashMap<String,String>();
        data.put("house_no", request.getHouseNo());
        data.put("people_no", peopleNo);
        map.put("data",JSONObject.toJSONString(data));
        sign= SfmMD5.md5(SfmUtils.createLinkString(map)+"&key="+appsecret).toUpperCase();
        map.put("sign", sign);
        result = sfmApi.bindRelPeopleHouse(map);
        jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return AjaxResult.error(jsonObject.get(MSG_TAG).toString() + (StringUtils.isNull(jsonObject.getJSONObject("data")) ? "" : "/" + jsonObject.getJSONObject("data").getString("synmsg")));
        }
        return  AjaxResult.success();
    }

    @Override
    public AjaxResult deletePeople(String peopleNo, String communityNo) {
        Map<String,String> params=new HashMap<String,String>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        params.put("communityno", communityNo);
        Map<String,String> data=new HashMap<String,String>();
        data.put("people_no", peopleNo);
        params.put("data",JSONObject.toJSONString(data));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.deletePeople(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return AjaxResult.error(jsonObject.get(MSG_TAG).toString());
        }
        return AjaxResult.success(jsonObject.get(MSG_TAG).toString());
    }

    @Override
    public AjaxResult getDeviceList(String peopleNo, String communityNo, String pageindex, String pagesize) {
        Map<String,String> params=new HashMap<String,String>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        params.put("communityno", communityNo);
        Map<String,String> data=new HashMap<String,String>();
        data.put("people_no", peopleNo);
        data.put("pageindex", pageindex);
        data.put("pagesize", pagesize);
        params.put("data",JSONObject.toJSONString(data));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.getDeviceList(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return AjaxResult.error(jsonObject.get(MSG_TAG).toString());
        }
        Object dataObj = jsonObject.get("data");
        List<SfmDeviceVO> sfmUserVOS = JSONObject.parseArray(dataObj.toString(), SfmDeviceVO.class);
        sfmUserVOS.forEach(item -> {
            SfmDeviceOnlineVO vo = getDeviceOnline(item.getDeviceNo(), communityNo);
            if (StringUtils.isNotNull(vo)) {
                item.setStatus(vo.getStatus());
            }
        });

        //TODO 获取设备状态（批量）
//        List<String> deviceNos = sfmUserVOS.stream().map(SfmDeviceVO::getDeviceNo).distinct().collect(Collectors.toList());
//        String devicenoarray = String.join(",", deviceNos);
//        List<SfmDeviceOnlineVO> onlineVOS = getDeviceListOnline(devicenoarray, communityNo);
//        Map<String, String> onlineMap = onlineVOS.stream().collect(Collectors.toMap(SfmDeviceOnlineVO::getDeviceno, SfmDeviceOnlineVO::getStatus));
//        sfmUserVOS.forEach(item -> {
//            if (StringUtils.isNotEmpty(onlineMap.get(item.getDeviceNo()))) {
//                item.setStatus(onlineMap.get(item.getDeviceNo()));
//            }
//        });

        return AjaxResult.success(sfmUserVOS);
    }

    private List<SfmDeviceOnlineVO> getDeviceListOnline(String devicenoarray, String communityNo) {
        Map<String,String> params=new HashMap<String,String>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        params.put("communityno", communityNo);
        Map<String,String> data=new HashMap<String,String>();
        data.put("devicenoarray", devicenoarray);
        params.put("data",JSONObject.toJSONString(data));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.getDeviceListOnline(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return new ArrayList<>(0);
        }
        Object dataObj = jsonObject.get("data");
        return JSONObject.parseArray(dataObj.toString(), SfmDeviceOnlineVO.class);
    }

    private SfmDeviceOnlineVO getDeviceOnline(String deviceNo, String communityNo) {
        Map<String,String> params=new HashMap<String,String>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        params.put("communityno", communityNo);
        Map<String,String> data=new HashMap<String,String>();
        data.put("device_no", deviceNo);
        params.put("data",JSONObject.toJSONString(data));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.getDeviceOnline(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return null;
        }
        SfmDeviceOnlineVO vo = new SfmDeviceOnlineVO();
        vo.setCode(jsonObject.getString(CODE_TAG));
        vo.setStatus(jsonObject.getString(MSG_TAG));
        return vo;
    }

    @Override
    public AjaxResult openDoor(SfmOpenDoorRequest request) {
        Map<String,String> params=new HashMap<String,String>();
        params.put("appid", appid);
        params.put("timestemp", getTimestemp());
        params.put("communityno", request.getCommunityNo());
        Map<String,String> data=new HashMap<String,String>();
        data.put("people_no", request.getPeopleNo());
        data.put("device_no", request.getDeviceNo());
        params.put("data",JSONObject.toJSONString(data));
        String sign= SfmMD5.md5(SfmUtils.createLinkString(params)+"&key="+appsecret).toUpperCase();
        params.put("sign", sign);
        String result = sfmApi.openDoor(params);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!SUCCESS_TAG.equals(jsonObject.get(CODE_TAG))) {
            return AjaxResult.error(jsonObject.get(MSG_TAG).toString());
        }
        return AjaxResult.success(jsonObject.get(MSG_TAG).toString());
    }

    @Override
    public AjaxResult selectHouse(SfmSelectHouseRequest request) {
        JrwhUser search = new JrwhUser();
        search.setPeoplePhone(request.getPhone());
        List<JrwhUser> list = jrwhUserService.selectJrwhUserList(search);
        List<JrwhUser> houseUserList = list.stream().filter(v -> request.getHouseNo().equals(v.getHouseNo())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(houseUserList)) {
            List<Long> ids = list.stream().map(JrwhUser::getId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(ids)) {
                List<JrwhUser> updateList = new ArrayList<>(ids.size());
                ids.forEach(item -> {
                    JrwhUser update = new JrwhUser();
                    update.setId(item);
                    update.setIsSelect(0);
                    updateList.add(update);
                });
                jrwhUserService.updateBatchById(updateList);
            }
            JrwhUser update = new JrwhUser();
            update.setId(houseUserList.get(0).getId());
            update.setIsSelect(1);
            jrwhUserService.updateById(update);
            JrwhUserInfoVO vo = OrikaUtil.convert(houseUserList.get(0), JrwhUserInfoVO.class);
            return AjaxResult.success(vo);
        }

        // TODO 从赛菲姆获取房屋住户信息 匹配当前手机号 存在则获取该用户的所有信息 记录到数据库 不存在则返回未找到该用户
        AjaxResult result = getListByHouseNo(request.getHouseNo(), request.getCommunityNo(), "1", "100");
        if (AjaxResult.isError(result)) {
            return result;
        }

        List<SfmUserVO> sfmUserVOS = JSONObject.parseArray(JSONObject.toJSONString(result.get(AjaxResult.DATA_TAG)), SfmUserVO.class);
        SfmUserVO sfmUserVO = sfmUserVOS.stream().filter(v -> request.getPhone().equals(v.getPeoplePhone())).findFirst().orElse(null);
        if (StringUtils.isNull(sfmUserVO)) {
            return AjaxResult.error("未找到对应用户");
        }

        List<Long> ids = list.stream().map(JrwhUser::getId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(ids)) {
            List<JrwhUser> updateList = new ArrayList<>(ids.size());
            ids.forEach(item -> {
                JrwhUser update = new JrwhUser();
                update.setId(item);
                update.setIsSelect(0);
                updateList.add(update);
            });
            jrwhUserService.updateBatchById(updateList);
        }

        JrwhUser insert = OrikaUtil.convert(request, JrwhUser.class);
        insert.setPeopleNo(sfmUserVO.getPeopleNo());
        insert.setPeopleName(sfmUserVO.getPeopleName());
        insert.setPeoplePhone(sfmUserVO.getPeoplePhone());
        insert.setPeoplePhoto(sfmUserVO.getPeoplePhoto());
        insert.setPeopleType(sfmUserVO.getPeopleType());
        insert.setIsSelect(1);

        boolean isSuccess = jrwhUserService.save(insert);
        if (!isSuccess) {
            return AjaxResult.error("选择房屋失败，添加用户信息失败");
        }

        return AjaxResult.success(OrikaUtil.convert(insert, JrwhUserInfoVO.class));
    }

    @Override
    public AjaxResult getUserInfo(String phone) {

        JrwhUser search = new JrwhUser();
        search.setPeoplePhone(phone);
        search.setIsSelect(1);
        List<JrwhUser> list = jrwhUserService.selectJrwhUserList(search);
        if (CollectionUtils.isEmpty(list)) {
            return AjaxResult.error(501, "请选择房屋");
        }
        if (list.size() > 1) {
            return AjaxResult.error("该用户已选中多个房屋，请联系管理员处理");
        }

        return AjaxResult.success(OrikaUtil.convert(list.get(0), JrwhUserInfoVO.class));
    }
}
